﻿package net.wangit.view.unit;

import java.util.ArrayList;
import java.util.List;

import net.wangit.MapList;
import net.wangit.Page;
import net.wangit.Row;
import net.wangit.context.ActionContext;
import net.wangit.framework.config.BeanFactory;
import net.wangit.framework.config.DomainsSettings;
import net.wangit.jdbc.DB;
import net.wangit.jdbc.ServerAccessException;
import net.wangit.jdbc.util.DBHelper;
import net.wangit.util.Checker;
import net.wangit.view.element.ElementComponent;
import net.wangit.view.element.ElementFactory;
import net.wangit.view.element.component.OrderElement;
import net.wangit.view.element.component.UnitElement;
import net.wangit.view.unit.component.QueryUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class UnitFactory {

	private static Log log = LogFactory
			.getLog(net.wangit.view.unit.UnitFactory.class);
	private static final String CALENDAR = "WdatePicker";
	private static final String CALENDAR_JS = "/common/datepicker/WdatePicker.js";
	private static final String SQL_UNIT = "select * from UNIT where uid=?";
	private static final String SQL_ELEMENT = "select * from ELEMENT where uid=? and s=1 order by o";

	public UnitFactory() {
	}

	public static synchronized UnitComponent getUnitWithoutClone(String domain,
			String unitId) {
		if (Checker.isEmpty(domain) || Checker.isEmpty(unitId)) {
			log.error(new StringBuilder(
					"empty arguments is not acceptable: domain=")
					.append(domain).append(" unitid=").append(unitId)
					.toString());
			return null;
		}
		unitId = unitId.toLowerCase();
		UnitComponent uc = UnitCache.get(domain, unitId);
		if (uc == null) {
			uc = createUnit(domain, unitId);
			UnitCache.put(domain, unitId, uc);
		}
		return uc;
	}

	public static UnitComponent getUnit(ActionContext ac, String domain,
			String unitId, Page page) {
		UnitComponent uc = getUnitWithoutClone(domain, unitId);
		return uc != null ? uc.cloneUnit(ac, page) : null;
	}

	private static UnitComponent createUnit(String domain, String unitId) {
		DB db = DBHelper.getDomainDB(domain);
		MapList list = null;
		try {
			list = db.query(UnitFactory.SQL_UNIT, unitId, 2);
		} catch (Exception e) {
			log.error((new StringBuilder("could not query unit in server: "))
					.append(domain).toString(), e);
			throw new ServerAccessException((new StringBuilder(
					"could not query unit in server: ")).append(domain)
					.toString(), e);
		}
		if (Checker.isEmpty(list)) {
			log.error((new StringBuilder("unit not found: ")).append(domain)
					.append("/").append(unitId).toString());
			throw new UnitConfigurationException((new StringBuilder(
					"unit not found: ")).append(domain).append("/")
					.append(unitId).toString());
		}
		Row row = list.getRow(0);
		String componentId = row.get("c");
		UnitComponent unit = null;
		try {
			unit = BeanFactory.getUnitComponent(componentId);
		} catch (Exception e) {
			log.error((new StringBuilder("could not load unit component: "))
					.append(domain).append("/").append(unitId).toString(), e);
			throw new UnitConfigurationException(
					"could not load unit component: ", domain, unitId,
					"component id", e);
		}
		unit.setId(unitId);
		unit.setDomain(domain);
		unit.setGroupId(row.get("gid"));
		unit.setColumn(row.getInt("co", 4));
		unit.setAddable("1".equals(row.get("ma")));
		unit.setEditable("1".equals(row.get("me")));
		unit.setScanable("1".equals(row.get("ms")));
		unit.setTableName(row.get("t"));
		unit.setListUnitId(row.get("x"));
		unit.setDataMode(row.getInt("dm", 1));
		String datasource = row.get("d");
		if (Checker.isEmpty(datasource))
			datasource = DomainsSettings.getDatasource(domain);
		unit.setDatasource(datasource);
		unit.setDataExpression(row.get("de"));
		unit.setHasAccessPrivileges("1".equals(row.get("au")));
		unit.setHasDataPrivilege(!Checker.isEmpty(row.get("dpid")));
		unit.setAppendInsertScript("1".equals(row.get("ais")));
		unit.setRemember("1".equals(row.get("r")));
		unit.setRecovery(!"0".equals(row.get("i3")));
		unit.setRowsConfigEnabled(!"0".equals(row.get("v7")));
		unit.setSwitchable("1".equals(row.get("i1")));
		unit.setInterceptors(row.get("ui"));
		unit.setPublished("1".equals(row.get("y")));
		unit.setTemplate(row.get("ut"));
		unit.setTableAttribute(row.get("ta"));
		String title = row.get("ti");
		unit.setTitle(title);
		unit.setName(title);
		unit.setShowTitle(!"0".equals(row.get("st")));
		unit.setTitleCss(row.get("v8"));
		unit.setToolbarCss(row.get("v9"));
		unit.setShowUnitBorder("1".equals(row.get("ub")));
		unit.setShowTitleBorder("1".equals(row.get("tb")));
		unit.setShowGridBorder(!"0".equals(row.get("gb")));
		unit.setShowCellBorder("1".equals(row.get("cb")));
		unit.setColsConfig(row.get("cc"));
		unit.setRowsConfig(row.get("rc"));
		unit.setLayoutMode(row.getInt("la", 0));
		unit.setGroupsConfig(row.get("g"));
		unit.setWidth(row.getInt("w", -1));
		unit.setWidthMode(row.getInt("wm", -1));
		unit.setHeight(row.getInt("h", -1));
		unit.setHeightMode(row.getInt("hm", -1));
		unit.setContent(row.get("pc"));
		unit.configure(row);
		try {
			list = db.query(UnitFactory.SQL_ELEMENT, unitId, 2);
		} catch (Exception e) {
			log.error(
					(new StringBuilder("could not query element in server: "))
							.append(domain).toString(), e);
			throw new ServerAccessException((new StringBuilder(
					"could not query element in server: ")).append(domain)
					.toString(), e);
		}
		if (!Checker.isEmpty(list))
			setElements(list, unit);
		return unit;
	}

	private static void setElements(MapList list, UnitComponent uc) {
		boolean isQueryUnit = uc instanceof QueryUnit;
		List<ElementComponent> elements = new ArrayList<ElementComponent>();
		for (int i = 0; i < list.size(); i++) {
			Row row = list.getRow(i);
			ElementComponent ec = ElementFactory.getElement(row, uc);
			ec.setParent(uc);
			uc.setHasElementAccessPrivileges(ec.hasAccessPrivilege());
			if (ec instanceof UnitElement)
				uc.setAppendInsertScript(false);
			else if (isQueryUnit && (ec instanceof OrderElement))
				((QueryUnit) uc).setOrderElementId(ec.getId());
			setJsCss(uc, row);
			elements.add(ec);
		}

		uc.setElements(elements);
	}

	private static void setJsCss(UnitComponent uc, Row row) {
		String custom = row.get("cu");
		String suffix = row.get("ws");
		String prefix = row.get("wp");
		if (!Checker.isEmpty(custom)
				&& custom.indexOf(UnitFactory.CALENDAR) > 0
				|| !Checker.isEmpty(suffix)
				&& suffix.indexOf(UnitFactory.CALENDAR) > 0
				|| !Checker.isEmpty(prefix)
				&& prefix.indexOf(UnitFactory.CALENDAR) > 0)
			uc.putElementTailJsPath(UnitFactory.CALENDAR_JS);
	}

}
